package com.carp.scaffolding.config;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.type.ITypeConvertHandler;
import com.baomidou.mybatisplus.generator.type.TypeRegistry;
import com.carp.scaffolding.config.prop.MyBatisPlusProperties;
import com.carp.scaffolding.config.prop.ProjectProperties;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Collections;

/**
 * @author lile
 * @date 2023/2/27
 */
@Configuration
@RequiredArgsConstructor
@ConditionalOnBean(MyBatisPlusProperties.class)
public class MyBatisPlusConfig {

    private final MyBatisPlusProperties myBatisPlusProperties;
    private final ProjectProperties projectProperties;

    /**
     * MyBaitsPlus 生成器配置
     * <a href="https://baomidou.com/pages/981406/#%E6%95%B0%E6%8D%AE%E5%BA%93%E9%85%8D%E7%BD%AE-datasourceconfig">...</a>
     */
    @Bean
    public AutoGenerator myBatisPlusGenerator(DataSourceConfig dataSourceConfig) {
        AutoGenerator generator = new AutoGenerator(dataSourceConfig);
        generator.global(globalConfig());
        generator.packageInfo(packageConfig());
        generator.strategy(strategyConfig());
        generator.template(templateConfig());
        return generator;
    }

    /**
     * 数据源配置
     */
    @Bean
    public DataSourceConfig dataSourceConfig(DataSourceProperties dataSourceProperties) {
        // 指定库名
        String url = dataSourceProperties.getUrl()
                .replace("/?", "/" + myBatisPlusProperties.getDatabase() + "?");
        return new DataSourceConfig
                .Builder(url, dataSourceProperties.getUsername(), dataSourceProperties.getPassword())
                .schema(myBatisPlusProperties.getDatabase())
                .typeConvertHandler(new ITypeConvertHandler() {
                    private final MySqlTypeConvert mySqlTypeConvert = new MySqlTypeConvert();

                    @Override
                    public IColumnType convert(GlobalConfig globalConfig, TypeRegistry typeRegistry, TableField.MetaInfo metaInfo) {
                        String fieldType = metaInfo.getJdbcType().name().toLowerCase();
                        if (fieldType.contains("tinyint")) {
                            return DbColumnType.INTEGER;
                        }
                        // 其它字段采用默认转换
                        return mySqlTypeConvert.processTypeConvert(globalConfig, fieldType);
                    }
                })
                .build();
    }

    /**
     * 全局配置
     */
    private GlobalConfig globalConfig() {
        return new GlobalConfig.Builder()
                .disableOpenDir()
                .outputDir(System.getProperty("user.dir") + "/output/" + projectProperties.getName() + "/src/main/java")
                .author("scaffolding")
                .enableSwagger()
                .dateType(DateType.TIME_PACK)
                .commentDate("yyyy-MM-dd")
                .build();
    }

    /**
     * 包配置
     */
    private PackageConfig packageConfig() {
        return new PackageConfig.Builder()
                .parent("com.ysb")
                .entity("model")
                .mapper("dao")
                .controller("web.controller")
                .service("service")
                .pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "/output/" + projectProperties.getName() + "/src/main/resources/mapper"))
                .build();
    }

    /**
     * 策略配置
     */
    private StrategyConfig strategyConfig() {
        StrategyConfig.Builder builder = new StrategyConfig.Builder()
                .enableSchema()
                .addTablePrefix(myBatisPlusProperties.getTablePrefix());

        if (StringUtils.isNotBlank(myBatisPlusProperties.getTables())) {
            builder.addInclude(myBatisPlusProperties.getTables());
        }

        return builder
                // entity
                .entityBuilder()
                .enableFileOverride()
                .enableLombok()
                .enableTableFieldAnnotation()
                // mapper
                .mapperBuilder()
                .enableFileOverride()
                .superClass(BaseMapper.class)
                .mapperAnnotation(Mapper.class)
                .enableBaseResultMap()
                .enableBaseColumnList()
                .formatMapperFileName("%sDao")
                .formatXmlFileName("%sMapper")
                // controller
                .controllerBuilder()
                .enableFileOverride()
                .enableRestStyle()
                // service
                .serviceBuilder()
                .enableFileOverride()
                .build();
    }

    /**
     * 模板配置
     */
    private TemplateConfig templateConfig() {
        return new TemplateConfig.Builder()
                .entity("/mbptemplates/entity.java")
                .build();
    }
}
